const SocketIo = require('socket.io');
const { onion } = require('./util');

class IoNameSpace {
  /**
   * socket.io命名空间
   * @param {socketIo.Socket} io 
   * @param {string} namespace 
   * @param {function[]} middlewareList 
   */
  constructor(io, namespace, middlewareList) {
    this.eventList = [];
    io.of(namespace, async (socket) => {
      onion(middlewareList, () => {
        for (const { eventName, controller } of this.eventList) {
          socket.on(eventName, () => {
            controller();
          });
        }
        return new Promise((resolve) => {
          socket.on('disconnect', resolve);
        });
      })(socket);
    });
  }

  /**
   * 定义事件映射
   * @param {string} eventName 事件类型
   * @param {function} controller 
   */
  router(eventName, controller) {
    this.eventList.push({ eventName, controller });
  }
}

class Io {
  /**
   * 初始化socket.io
   * @param {import('http').Server} server http server
   */
  constructor(server) {
    this.io = SocketIo(server);
  }

  /**
   * 定义命名空间
   * @param {string} namesapce 空间名称
   * @param  {...any} middlewareList 连接事件触发的中间件列表
   */
  of(namesapce, ...middlewareList) {
    return new IoNameSpace(this.io, namesapce, middlewareList);
  }
}

exports.Io = Io;